package com.tdd;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

import java.util.concurrent.CountDownLatch;

/**
 * @author tudedong
 * @description
 * @date 2020-07-11 12:51:05
 */
public class ZkTemplateImplLock extends AbstractTemplateLock{

    private static final String ZK_ADDRES = "47.101.41.95:2181";

    private static final int TIMEOUT = 5000;

    private ZkClient zkClient = new ZkClient(ZK_ADDRES,TIMEOUT);

    private String lockPath = "/lockPath";

    private CountDownLatch countDownLatch = null;

    @Override
    protected boolean tryLock() {
        //获取锁思路：多个线程创建临时节点，谁创建成功谁就获得锁
        try{
            zkClient.createEphemeral(lockPath);
            return true;
        }catch (Exception e){
            //如果节点已经存在
            e.printStackTrace();
            return false;
        }
    }

    @Override
    protected void waitLock() {
        //1.事件监听，监听/lockPath节点是否已经被删除，若删除可以重新获得锁
        zkClient.subscribeDataChanges(lockPath, new IZkDataListener() {
            @Override
            public void handleDataChange(String s, Object o) throws Exception {

            }

            @Override
            public void handleDataDeleted(String s) throws Exception {
                //3.如果节点被删除，需要重新获取锁
                if(countDownLatch != null){
                    //将计算变为0
                    countDownLatch.countDown();

                }

            }
        });
        //2.使用CountDownLatch进行等待
        if(countDownLatch == null){
            countDownLatch = new CountDownLatch(1);
        }
        try {
            //如果当前计数器不为0，就一直等待
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void unLockImpl() {
        //关闭zk连接
        if(zkClient != null){
            zkClient.close();
            System.out.println(Thread.currentThread().getName()+"，释放锁，，，");
        }
    }
}
